#ifndef SROS_DEVICE_MCU_DEVICE_HPP
#define SROS_DEVICE_MCU_DEVICE_HPP

#include "config/mcu_config.hpp"
#include "device_impl.hpp"
#include "devices/detail/proto.hpp"

#include <map>
#include <mutex>
#include <functional>

namespace sros
{
    namespace net
    {
        class TcpClient;
    }

    namespace async
    {
        class Timer;
    }
}

namespace sros::device
{
    class McuDevice final : public device_impl<cfg::McuCfg>
    {
    public:
        McuDevice() = default;
        ~McuDevice() override;

        RetBool init() override;

        void run() override;

        void close() override;

        // CAN接口状态数据回调接口
        using on_can_status_arrival = std::function<void(const proto::CanStatus &)>;
        inline void install_can_status_cb(on_can_status_arrival cb) { can_status_cb_ = cb; }

        // UART设备接口状态数据回调接口
        using on_uart_status_arrival = std::function<void(const proto::UartStatus &)>;
        inline void install_uart_status_cb(on_uart_status_arrival cb) { uart_status_cb_ = cb; }

        // CAN数据达到回调接口
        using on_can_msg_arrival = std::function<void(const proto::RspCanMsg &)>;
        inline void install_can_msg_cb(on_can_msg_arrival cb) { can_msg_cb_ = cb; }

        // 串口数据达到回调接口
        using on_uart_msg_arrival = std::function<void(const proto::RspUartMsg &)>;
        inline void install_uart_msg_cb(on_uart_msg_arrival cb) { uart_msg_cb_ = cb; }

        // IO数据达到回调接口
        using on_io_msg_arrival = std::function<void(const proto::RspIoMsg &)>;
        inline void install_io_msg_cb(on_io_msg_arrival cb) { io_msg_cb_ = cb; }

        // 控制板信息数据达到回调接口
        using on_version_msg_arrival = std::function<void(const proto::RspVersionMsg &)>;
        inline void install_version_msg_cb(on_version_msg_arrival cb) { version_msg_cb_ = cb; }

        // 电源引脚状态数据回调接口
        using on_power_status_arrival = std::function<void(const std::map<uint32_t, bool> &)>;
        inline void install_power_status_cb(on_power_status_arrival cb) { power_status_cb_ = cb; }

        // 编码器数据到达回调接口
        using on_encoder_msg_arrival = std::function<void(const std::map<uint32_t, int32_t> &)>;
        inline void install_encoder_msg_cb(on_encoder_msg_arrival cb) { encoder_cb_ = cb; }

        // 发送 can 数据
        RetBool send_can_msg(const proto::ReqCanMsg &msg);

        // 发送 uart 数据
        RetBool send_uart_msg(const proto::ReqUartMsg &msg);

        // 电源控制
        RetBool power_ctl(const uint8_t &id, const bool &is_on);

        // 所有的CAN口状态
        std::map<uint32_t, proto::CanStatus> cans_status() 
        {
            std::lock_guard<std::mutex> lck(cans_status_mtx_);
            return cans_status_;
        }

        // 所有的串口状态
        std::map<uint32_t, proto::UartStatus> uarts_status()
        {
            std::lock_guard<std::mutex> lck(uarts_status_mtx_);
            return uarts_status_;
        }

        // 所有电源引脚状态
        std::map<uint32_t, bool> power_status()
        {
            std::lock_guard<std::mutex> lck(power_status_mtx_);
            return power_status_;
        }

    protected:
        // 配置加载
        RetBool load_config() override;

    private:
        // 定时器触发回调接口
        void on_timer_trigger_(std::size_t times);

        // 初始化外设接口状态
        void init_dev_status_();

        // 初始化TCP client
        RetBool init_tcp_client_();

        // 初始化回调接口列表
        void init_cb_list_();

    private:
        on_can_status_arrival   can_status_cb_;      // CAN口状态
        on_uart_status_arrival  uart_status_cb_;     // 串口状态
        on_power_status_arrival power_status_cb_;    // 电源状态
        on_can_msg_arrival      can_msg_cb_;         // CAN口数据
        on_uart_msg_arrival     uart_msg_cb_;        // 串口数据
        on_io_msg_arrival       io_msg_cb_;          // IO口数据
        on_version_msg_arrival  version_msg_cb_;     // 版本信息
        on_encoder_msg_arrival  encoder_cb_;         // 编码器

        std::mutex cans_status_mtx_;
        std::mutex uarts_status_mtx_;
        std::mutex power_status_mtx_;

        std::map<uint32_t, proto::CanStatus>  cans_status_;   // 所有CAN口状态
        std::map<uint32_t, proto::UartStatus> uarts_status_;  // 所有UART口状态
        std::map<uint32_t, bool>              power_status_;  // 所有电源引脚状态

        std::shared_ptr<net::TcpClient>  client_ = nullptr;
        std::shared_ptr<async::Timer>    timer_ = nullptr;
    };

} // namespace name

#endif